import requests
from lxml import etree
import os
import re
from multiprocessing.dummy import Pool  # 线程池

# 11.异步爬取梨视频(难点:所爬取的MP4不在源代码,而藏在动态网络请求中)
# 步骤总结:
# 爬取梨视频首页; 找到首页各视频的网页地址,名称等; 在网页地址中分隔字符串得到code; 利用code向一解析出的网页地址请求得到视频地址; 更改视频地址格式; 爬取视频
if True:
    finished = 0  # 进度条工具
    pool = Pool(5)  # 实例化一个线程池
    session = requests.Session()
    url = "https://www.pearvideo.com/category_5"
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) "
                      "Chrome/86.0.4240.198 Safari/537.36 "
    }
    response = session.get(url=url, headers=headers)  # 爬取梨视频首页
    page_text = response.text
    parser = etree.HTMLParser(encoding="utf-8")
    tree = etree.HTML(page_text, parser)
    a = "https://www.pearvideo.com/"
    video_list = tree.xpath('//div[@class="vervideo-bd"]/a')  # 找到首页的所有视频
    videos = []
    for video in video_list:
        dress = a + video.xpath('./@href')[0]  # 拼接出视频网址(注意,这不是我们最终需要的MP4地址！MP4地址需要在抓包工具中解析！)
        _img_dress = video.xpath('.//div[@class="img"]/@style')[0]
        img_dress = re.findall(': url\((.*?)\)', _img_dress)[0]  # 视频封面地址
        title = video.xpath('.//div[@class="vervideo-title"]/text()')[0]  # 标题
        print(dress, "__", img_dress, title)
        videos.append({"dress": dress, "img_dress": img_dress, "title": title})


def get_mp4(html):
    global finished  # 沿用全局变量
    html_dress = html["dress"] #在html字典里取出值
    mp4_name = html["title"] #在html字典里取出值
    global parser  # 沿用全局变量
    _headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) "
                      "Chrome/86.0.4240.198 Safari/537.36 ",
        "Referer": html_dress
    }
    code = html_dress.split('_')[-1]  # 视频编码,经解析通常为7位数字，截取网址中最后一个横杠后面的字符
    real_dress = 'https://www.pearvideo.com/videoStatus.jsp?contId={}'.format(code)  # 根据解析发现MP4不在源代码中,
    # 而是在一个网络请求中,需向real_dress请求以得到MP4的地址
    # print(real_dress)
    rsp = session.get(url=real_dress, headers=_headers)  # 向real_dress请求
    rsp_txt = eval(rsp.text)  # 得到包含MP4的地址的一段信息
    _src = rsp_txt['videoInfo']['videos']['srcUrl']  # 提取MP4地址，进行截取
    mp4_src = re.findall("(.*/).*?-", _src)[0] + "cont-{}-".format(code) + re.findall(".*/.*?-(.*)", _src)[0]
    # 经解析,发现要更改地址格式才能成功爬取,这一步是更改地址格式
    # print(mp4_src) # 更改后的地址(能打开)
    # print(_src) # 原格式地址(打不开)
    if not os.path.exists('./梨视频'):
        os.mkdir('./梨视频')
    print("《{}》正在下载".format(mp4_name))
    mp4 = session.get(url=mp4_src, headers=_headers)  # 得到视频
    with open("梨视频/{}.mp4".format(code), 'wb') as _fp:  # 保存的视频名称为对应的code,防止文件名报错
        _fp.write(mp4.content)
        finished += 1
        print("{}下载完成! {}/{}".format(mp4_name, finished, len(videos)))


pool.map(get_mp4, videos)


# format用法：{}  {} {}.format(A,B,C),即可依次将ABC填入{}中，还具有格式化和校验的功能，优于直接输出。
